import {
  BaseUrlType,
  RequestConfigTypes
} from "@/types/request";
import baseUrl from './baseUrl';
import { useUserStore } from "@/stores/user";

const getContentType = function (config: RequestConfigTypes) {
  let type = config.contentType || "json";
  let charset = "UTF-8";
  if (type === "json") {
    return "application/json;charset=" + charset;
  } else if (type === "form") {
    return "application/x-www-form-urlencoded;charset=" + charset;
  } else if (type === "file") {
    return "multipart/form-data;charset=" + charset;
  } else if (type === "text") {
    return "text/plain;charset=" + charset;
  } else if (type === "html") {
    return "text/html;charset=" + charset;
  } else {
    throw new Error("unsupported content type : " + type);
  }
}

// 请求前处理config
const requestBeforeHook = function (config: RequestConfigTypes) {
  const _nodeEnv = window.location.hostname.indexOf('test') !== -1 ? `${process.env.NODE_ENV}_test` : process.env.NODE_ENV;
  config.url = baseUrl[_nodeEnv as BaseUrlType] + (config.url || "");

  const token = uni.getStorageSync('token');
  const _config = {
    header: {
      "Content-Type": getContentType(config),
      "Authorization": token ? `Bearer ${token}` : ''
    },
    timeout: 6000,
  }
  return Object.assign(_config, config);
}



class Request {
  // 响应正常处理
  _success(config: RequestConfigTypes, response: any, resolve: any, reject: any) {
    let { statusCode, data } = response;
    if(config.contentType === 'file' && typeof(data) === 'string'){
      data = JSON.parse(data)
    }
    const code = (data as AnyObject)?.code ?? 200;// 未设置状态码则默认成功状态
    let msg = (data as AnyObject).msg ?? '服务器连接异常 请联系客服'; // 后端返回提示信息 
    if (statusCode === 200 && code === 200) {
      resolve(data);
    } else {
      if (code === 401) { // token过期
        msg = '登录过期,请重新登录'
        const { logOut } = useUserStore();
        logOut();
      }
      uni.showToast({
        title: msg,
        duration: 2000,
        icon: "error",
      });
      reject({ code, msg });
    }
  };
  // 响应错误处理
  _fail(config: RequestConfigTypes, error: any, resolve: any, reject: any) {
    uni.showToast({
      title: '服务器连接超时 请检查网络',
      duration: 2000,
      icon: "error",
    });
    reject(error);
  };

  /**
  * @description request请求方法
  */
  request(config: RequestConfigTypes): Promise<any> {
    let conf = uni.$u.deepClone(config) as RequestConfigTypes;
    // 处理请求前的config
    if (requestBeforeHook && typeof requestBeforeHook === "function") {
      conf = requestBeforeHook(conf as RequestConfigTypes);
    }
    return new Promise(async (resolve, reject) => {
      if (!conf.header['Authorization'] && !conf.isWhiteList) {
        reject({ code: 500, msg: "缺少token且接口未设置白名单" });
        return
      }
      const that = this;
      if (conf.contentType === 'file') {
        uni.uploadFile({
          url: conf.url,//开发者服务器 url
          filePath: (conf.data as { url: string }).url,//要上传文件资源的路径
          name: conf.contentType,//必须填file
          header: { Authorization: conf.header.Authorization },
          success: function (response) {
            that._success(conf, response, resolve, reject);
          },
          fail: function (error) {
            that._fail(conf, error, resolve, reject)
          }
        })
      } else {
        uni.request({
          ...conf,
          success: (response) => {
            that._success(conf, response, resolve, reject);
          },
          fail: (error) => {
            that._fail(conf, error, resolve, reject);
          },
        })
      }
    })
  }
}

const requestInstance = new Request();
export default requestInstance.request.bind(requestInstance);